﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConditionJudge.Question;

namespace ConditionJudge.Answer
{
    class Effie : IConditionJudge
    {
        List<char> listOpr = new List<char>();
 

        public string Judgement(string expression, int x)
        {
            listOpr.Add('=');
            listOpr.Add('!');
            listOpr.Add('>');
            listOpr.Add('<');

            expression = expression.Replace("X", x.ToString()).Replace("&&", "&").Replace("||", "|");

            Stack<char> tkConditions = new Stack<char>();
            for (int i = 0; i < expression.Length; i++)
            {
                char ch = expression[i];

                if (ch == ' ')
                    continue;

                if (ch == ')')
                {
                    if (tkConditions.Count == 0 || !tkConditions.Contains('('))
                        return "FF";

                    string strTemp = "";
                    while (tkConditions.Count > 0)
                    {
                        char cTemp = tkConditions.Pop();
                        strTemp += cTemp;
                        if (cTemp == '(')
                            break;
                    }

                    char chChkUnit = this.ChkUnitLogical(this.Reverse(strTemp));
                    if (!chChkUnit.Equals(' '))
                        tkConditions.Push(chChkUnit);
                    else
                        return "FF";
                }
                else
                {
                    tkConditions.Push(ch);
                }

                if (i == expression.Length - 1)
                {
                    if (tkConditions.Contains('('))
                    {
                        return "FF";
                    }
                    else
                    {
                        string strTemp = "";
                        while (tkConditions.Count > 0)
                            strTemp += tkConditions.Pop();
                        char result = this.ChkUnitLogical(this.Reverse(strTemp));
                        if (result == ' ')
                            return "FF";
                        else
                            return "T" + result.ToString();

                    }
                }
            }

            return "FF";
        }

        /// <summary>
        /// 校验最小连续单元逻辑是否正确
        /// </summary>
        /// <param name="str">最小连续单元</param>
        /// <returns>如果逻辑正确或错误,返回T或F;否则返回空</returns>
        private char ChkUnitLogical(string strUnit)
        {
            if (strUnit.Contains("("))
                strUnit = strUnit.Substring(1, strUnit.Length - 1);
            strUnit = strUnit.Trim();
            if (strUnit.Equals(""))
                return ' ';
            //最小连续单元不能同时存在&和|运算符
            if (strUnit.Contains("&") && strUnit.Contains("|"))
                return ' ';
            //如果存在&运算符
            if (strUnit.Contains("&"))
            {
                /*
                 * 匹配规则：
                 *   将字符串按照&拆分，则拆分后数组均为条件明细；
                 *   只要其中有个为假，则为假；否则为真；
                 */
                string[] strs = strUnit.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strs.Length; i++)
                {
                    char chRes = this.CompareUnit(strs[i]);
                    if (!chRes.Equals('T'))
                        return chRes;
                }
                return 'T';
            }
            //如果存在|运算符
            else if (strUnit.Contains("|"))
            {
                /*
                 * 匹配规则：
                 *   将字符串按照&拆分，则拆分后数组均为条件明细；
                 *   只要其中有个为真，则为真；否则为假；
                 */
                string[] strs = strUnit.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strs.Length; i++)
                {
                    char chRes = this.CompareUnit(strs[i]);
                    if (!chRes.Equals('F'))
                        return chRes;
                }
                return 'F';
            }
            else
            {
                /*
                 * 匹配规则：
                 *   该最小单元要么为T，要么为F，要么为条件明细
                 */
                if (strUnit.Equals("T"))
                    return 'T';
                else if (strUnit.Equals("F"))
                    return 'F';
                else
                    return this.CompareUnit(strUnit);
            }
        }
        /// <summary>
        /// 比较字符串是否成立
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>如果逻辑正确，返回T；逻辑错误，返回F，否则返回空</returns>
        private char CompareUnit(string str)
        {
            if(str.Trim().Equals("T"))
                return 'T';
            else if(str.Trim().Equals("F"))
                return 'F';
            int iRight, iLeft;

            string strRight = "", strLeft = "";
            string strOpr = "";

            foreach (char ch in str)
            {
                if (ch == ' ')
                    continue;

                if (listOpr.Contains(ch) && !strRight.Trim().Equals(""))
                    return ' ';
                else if (listOpr.Contains(ch))
                    strOpr += ch;
                else if (strOpr.Trim().Equals(""))
                    strLeft += ch;
                else
                    strRight += ch;
            }

            if (strOpr.Equals(""))
                return 'T';

            try
            {
                iLeft = Convert.ToInt32(strLeft);
            }
            catch (Exception)
            {
                return ' ';
            }

            try 
            {
                iRight = Convert.ToInt32(strRight);
            }
            catch (Exception)
            {
                return ' '; 
            }

            switch (strOpr)
            {
                case "=":
                    if(iLeft.Equals(iRight))
                        return 'T';
                    else
                        return 'F';
                case "!=":
                    if (iLeft.Equals(iRight))
                        return 'F';
                    else
                        return 'T';
                case ">=":
                    if (iLeft >= iRight)
                        return 'T';
                    else
                        return 'F';
                case ">":
                    if (iLeft > iRight)
                        return 'T';
                    else
                        return 'F';                   
                case "<=":
                    if (iLeft <= iRight)
                        return 'T';
                    else
                        return 'F';
                case "<":
                    if (iLeft < iRight)
                        return 'T';
                    else
                        return 'F';
                default:
                    return ' ';
            }
        }
        /// <summary>
        /// 反转字符串
        /// </summary>
        /// <param name="strOrignal">原始字符串</param>
        /// <returns>反转后字符串</returns>
        private string Reverse(string strOrignal)
        {
            char[] arrOrignal = strOrignal.ToCharArray();
            Array.Reverse(arrOrignal);
            return new string(arrOrignal);
        }
    }
}
